/*
(c) 2010 - Open Source Business Foundation e. V. (www.osbf.de)
This software is provided under Microsoft Reciprocal License (Ms-RL)
(http://www.microsoft.com/opensource/licenses.mspx#Ms-RL)
All other rights reserved
*/

const HCARD_CLASS = "vcard";
const HCALENDAR_CLASS = "vevent";
const HREVIEW_CLASS = "hreview";
const MICROFORMAT_CLASSES = [ HCARD_CLASS, HCALENDAR_CLASS, HREVIEW_CLASS ];
const RE_MAILTO = new RegExp(/mailto:([^\?]+)/);

function findMicroFormatNodes(node) {
  var microFormatNodes = new Array();
  var descent = true;
  if (node.nodeType == Node.ELEMENT_NODE) {
    var classAttr = node.getAttribute("class");
    if (classAttr) {
      for (var i = 0; (descent && (i < MICROFORMAT_CLASSES.length)); i++) {
        if (classAttr == MICROFORMAT_CLASSES[i]) {
          microFormatNodes.push(node);
          descent = false;
        }
      }
    }
  }
  if (descent) {
    var children = node.childNodes;
    for (var i = 0; i < children.length; i++) {
      var microFormatChildren = findMicroFormatNodes(children[i]);
      for (var j = 0; j < microFormatChildren.length; j++) {
        microFormatNodes.push(microFormatChildren[j]);
      }
    }
  } 
  return microFormatNodes;
}

function findClassNodes(node) {
  var classNodes = new Array();
  if (node.nodeType == Node.ELEMENT_NODE) {
    var classAttr = node.getAttribute("class");
    if (classAttr) {
      classNodes.push(node);
    }
  }
  var children = node.childNodes;
  for (var i = 0; i < children.length; i++) {
    var classNodeChildren = findClassNodes(children[i]);
    for (var j = 0; j < classNodeChildren.length; j++) {
      classNodes.push(classNodeChildren[j]);
    }
  } 
  return classNodes;
}

function parseMicroFormats(node) {
  var microFormats = new Array();
  var microFormatNodes = findMicroFormatNodes(node);
  if (microFormatNodes.length > 0) {
    for (var i = 0; i < microFormatNodes.length; i++) {
      var microFormat = parseMicroFormatNode(microFormatNodes[i]);
      if (microFormat != null) {
        microFormats.push(microFormat);
      }
    }
  }
  return microFormats;
}

function parseMicroFormatNode(node) {
  var classAttr = node.getAttribute("class");
  if (HCARD_CLASS == classAttr) {
    var hCard = { };
    var classNodeChildren = findClassNodes(node, true);
    for (var i = 0; i < classNodeChildren.length; i++) {
      processHcardChildNode(hCard, classNodeChildren[i]);
      hCard["mfType"] = "hCard"
      hCard["mfName"] = hCard["fn"];
    }
    return hCard;
  }
  if (HCALENDAR_CLASS == classAttr) {
    var hCalendar = { };
    var classNodeChildren = findClassNodes(node, true);
    for (var i = 0; i < classNodeChildren.length; i++) {
      processHcalendarChildNode(hCalendar, classNodeChildren[i]);
      hCalendar["mfType"] = "hCalendar"
      hCalendar["mfName"] = hCalendar["summary"];
    }
    return hCalendar;
  }
  if (HREVIEW_CLASS == node) {
    var hReview = { };
    var classNodeChildren = findClassNodes(node, true);
    for (var i = 0; i < classNodeChildren.length; i++) {
      processHreviewChildNode(hReview, classNodeChildren[i]);
      hReview["mfType"] = "hReview"
      hReview["mfName"] = hReview["summary"];
    }
    return hReview;
  }
  return null;
} 

function processHcardChildNode(hCard, node) {
  
  if (isElementOfClass(node, "url")) {
    var url = findAttributeNodes(node, "href");
    if (url.length > 0) {
      hCard["url"] = fullUrl(node.ownerDocument, url[0]);
    }
  }
  
  if (isElementOfClass(node, "email")) {
    var email = node.getAttribute("href");
    if (!email) {
      email = mfo_text(node);
    }
    if (email.match(RE_MAILTO)) {
      email = RegExp.$1;
    }
    hCard["email"] = email;
  }

  mfo_setProps(node, hCard, ["fn", "given-name", "family-name", "title", "note", "tel", "org", "locality", "region" ]);

  if (isElementOfClass(node, "logo")) {
    hCard["logo"] = fullUrl(node.ownerDocument, node.getAttribute("src"));
  }

  if (isElementOfClass(node, "latitude")) {
    var geolat = node.getAttribute("title");
    if (!geolat) {
      geolat = mfo_text(node);
    }
    hCard["geolat"] = geolat;
  }

  if (isElementOfClass(node, "longitude")) {
    var geolon = node.getAttribute("title");
    if (!geolon) {
      geolon = mfo_text(node);
    }
    hCard["geolon"] = geolon;
  }
}

function findAttributeNodes(node, attrName) {
  var attributeNodes = new Array();
  var descent = true;
  if (node.nodeType == Node.ELEMENT_NODE) {
    var attr = node.getAttribute(attrName);
    if (attr) {
      attributeNodes.push(attr);
      descent = false;
    }
  }
  if (descent) {
    var children = node.childNodes;
    for (var i = 0; i < children.length; i++) {
      var attributeNodeChildren = findAttributeNodes(children[i], attrName);
      for (var j = 0; j < attributeNodeChildren.length; j++) {
        attributeNodes.push(attributeNodeChildren[j]);
      }
    }
  } 
  return attributeNodes;
}

function processHcalendarChildNode(hCalendar, node) {
  
  if (isElementOfClass(node, "url")) {
    hCalendar["url"] = fullUrl(node.ownerDocument, node.getAttribute("href"));
  }
    
  mfo_setPropsFromAttr(node, hCalendar, ["dtstart", "dtend"], "title");
  mfo_setProps(node, hCalendar, ["summary","location","comment", "description", "location", "contact", "sequence", "priority", "dtstamp", "last-modified", "created", "recurrence-id", "attendee", "organizer"]);

  if (isElementOfClass(node, "latitude")) {
    var geolat = node.getAttribute("title");
    if (!geolat) {
      geolat = mfo_text(node);
    }
    hCalendar["geolat"] = geolat;
  }

  if (isElementOfClass(node, "longitude")) {
    var geolon = node.getAttribute("title");
    if (!geolon) {
      geolon = mfo_text(node);
    }
    hCalendar["geolon"] = geolon;
  }

}

function processHreviewChildNode(hReview, node) {

  if (isElementOfClass(node, "item")) {
    var item = processHreviewItemNode(node);
    if (item != null) {
      hReview["item"] = item;
    }
  }

  if (isElementOfClass(node, "reviewer")) {
    var reviewer = processHreviewReviewerNode(node);
    if (reviewer != null) {
      hReview["reviewer"] = reviewer;
    }
  }

  mfo_setProps(node, hReview, ["rating", "description", "summary", "type", "version"]);
  mfo_setPropsFromAttr(node, hReview, ["dtreviewed"], "title");

  if (isElementOfClass(node, "url")) {
    hReview["url"] = fullUrl(node.ownerDocument, node.getAttribute("href"));
  }
  
}

// TODO: this may be an hCard or an hCalendar object
function processHreviewItemNode(node) {
  var item = { };
  mfo_setProps(node, item, ["fn"]);
  return item;
}

function processHreviewReviewerNode(node) {
  var microFormatNodes = findMicroFormatNodes(node);
  if (microFormatNodes.length > 0) {
    return parseMicroFormatNode(microFormatNodes[0]);
  } else {
    return null;
  }
}

function isElementOfClass(node, cls) {
  var result = false;
  if (node && (node.nodeName != "#text") && (node.nodeName != "#comment")) {
    var classAttr = node.getAttribute("class");
    if (classAttr) {
      result = classAttr.match(new RegExp("\\b" + cls + "\\b"));
    }
  }
  return result;
}

/* get the child text of a node, skipping over elements nodes */
function mfo_text(e) {
  var t = null;
  if (e.tagName && e.tagName.toLowerCase() == "abbr")
    return e.getAttribute("title");
  else if (e.tagName.toLowerCase() == "img")
    return e.getAttribute("alt");
  return trim(mfo_text1(e));
}

function mfo_text1(e) {
  if (e.data && e.data.length > 0) {
    return e.data;
  }
  if (e.hasChildNodes) {
    var s = "";
    var children = e.childNodes;
    for (var i=0; i<children.length; i++) {
      // skype plugin fix -->
      if (children.item(i).nodeType == Node.ELEMENT_NODE) {
        var classAttr = children.item(i).getAttribute("class");
        if ("skype_pnh_container" != classAttr) {
          s += mfo_text1(children.item(i));
        }
      } else {
      // <-- skype plugin fix
         s += mfo_text1(children.item(i));
      }
    }
    return s;
  }
  return "";
}

/* setting a property of the format object from the text of the given
   node if node is of the specified class */
function mfo_setProps(node, foObj, clsArr) {
  for (var i=0; i<clsArr.length; i++) {
    if (isElementOfClass(node, clsArr[i])) {
      foObj[clsArr[i]] = mfo_text(node);
    }
  }
}

/* setting a property of the format object from an attribute of the
   given node if node is of the specified class */
function mfo_setPropsFromAttr(node, foObj, clsArr, attr) {
  for (var i=0; i<clsArr.length; i++) {
    if (isElementOfClass(node, clsArr[i])) {
      foObj[clsArr[i]] = node.getAttribute(attr);
    }
  }
}

